#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <math.h>
#include <json-c/json.h>
#include "fpga_interface.h"
#include "RealtimeWaveform.h"
#include "dataBase/errWaveFunction.h"
#include "ErrorLog.h"
#include "debug.h"
#include <pthread.h>
#include <unistd.h>
#include <sys/syscall.h>
#include "misc.h"
#include <sys/time.h>
#include <signal.h>
#include <time.h>
#include <stdint.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/socket.h>

#define FPGA_WAVE_FIFO_INDEX (503)

#define ERROR_WAVE_HEAD_GROUP_QTY    (30) /* 记录发生故障时前30组波形数据 */
#define ERROR_WAVE_TAIL_GROUP_QTY    (10) /* 记录发生故障时后10组波形数据 */

/* 波形数据刷新频率由FPGARAM_INDEX_100进行设置,范围为(1-10kHz),也就是一秒钟可产生(1-10000)个波形数据 */
#define MIN_WAVEFORM_SAMPLE_FREQ   (1)
#define MAX_WAVEFORM_SAMPLE_FREQ   (10000)

#define FPGA_PIN_DEV "/dev/fpga"

const char* fifoName[WAVEFORM_FIFO_QTY] = {"fifo1", "fifo2", "fifo3", 
                                            "fifo4", "fifo5", "fifo6", 
                                            "fifo7", "fifo8", "fifo9"};

struct realtimeGroupWaveData realtimeGroupDataBuff;

realtimeWaveDataType_t realtimeWaveData = {.rwdt_pRealtimeGroupWaveData = &realtimeGroupDataBuff};

struct realtimeWaveDataSyncInfo realtimeSyncInfo;

int16_t sinRatio[9][100];

void setRealtimeSyncSendFlag(uint8_t flag){
    realtimeSyncInfo.syncSendFlag = flag;
}

uint8_t getRealtimeSyncSendFlag(void){
    return realtimeSyncInfo.syncSendFlag;
}

void setRealtimeSyncSendSocketFd(int fd){
    realtimeSyncInfo.sendSocketFd = fd;
}

int getRealtimeSyncSendSocketFd(void){
    return realtimeSyncInfo.sendSocketFd;
}

uint32_t getCurrentWaveDataGroupIndex(void){
    return realtimeGroupDataBuff.currentGroupIndex;
}

uint32_t getSendGroupIndex(void){
    return realtimeSyncInfo.sendGroupIndex;
}

void setSendGroupIndex(uint32_t groupIndex){
    realtimeSyncInfo.sendGroupIndex = groupIndex;
}

void sendGroupIndexIncrement(void){
    realtimeSyncInfo.sendGroupIndex++;
}

uint16_t waveformSampleFpgaFifoRead(int fifoIndex){
    uint16_t fifoData;
    FpgaInf_Read(FPGA_WAVE_FIFO_INDEX + fifoIndex, &fifoData);
    return fifoData;
}

void waveformSampleEnqueue(uint16_t dataIndex, uint16_t* pChannelData){

    int fifoIndex = 0;

    for(fifoIndex = 0; fifoIndex < WAVEFORM_FIFO_QTY; fifoIndex++){
        realtimeWaveData.rwdt_oneGroupWaveData.waveData[fifoIndex][dataIndex] = pChannelData[fifoIndex];
    }
}

//拷贝一组波形数据到实时波形数据组
void oneGroupWaveDataCopy(struct oneGroupWaveData* pGroupWaveData){

    int groupWaveDataIndex = 0;

    groupWaveDataIndex = realtimeGroupDataBuff.currentGroupIndex % WAVEFORM_GROUP_DEPTH;

    memcpy(&(realtimeGroupDataBuff.groupWaveData[groupWaveDataIndex]), pGroupWaveData, sizeof(struct oneGroupWaveData));
}

//实时波形数据封装
int realtimeWaveDataPackageFrame(int fifoIndex, uint32_t curGroupIndex, uint8_t* rsp){

    int byteIndex = 0;
    uint32_t dataIndex = 0;
    uint16_t waveData = 0;
    int oneGroupIndex = (curGroupIndex - 1) % WAVEFORM_GROUP_DEPTH;
    uint16_t* oneFifoWaveData = NULL;
    
    oneFifoWaveData = (uint16_t*)&(realtimeGroupDataBuff.groupWaveData[oneGroupIndex].waveData[fifoIndex]);

    //modbus头
    rsp[byteIndex++] = 0;
    rsp[byteIndex++] = 0;
    rsp[byteIndex++] = 0;
    rsp[byteIndex++] = 0;
    //modbus帧长度
    rsp[byteIndex++] = 0;
    rsp[byteIndex++] = 0;
    //单元标识符
    rsp[byteIndex++] = 0;
    //功能码
    rsp[byteIndex++] = 100;
    //fifo通道标识
    rsp[byteIndex++] = fifoIndex;
    //data index 实时组索引-1×fifo depth
    dataIndex = (curGroupIndex - 1) * WAVEFORM_FIFO_DEPTH;
    rsp[byteIndex++] = (uint8_t)(dataIndex >> 24);
    rsp[byteIndex++] = (uint8_t)(dataIndex >> 16);
    rsp[byteIndex++] = (uint8_t)(dataIndex >> 8);
    rsp[byteIndex++] = (uint8_t)(dataIndex);
    //发送多少个波形数据点
    rsp[byteIndex++] = (uint8_t)(WAVEFORM_FIFO_DEPTH >> 8);
    rsp[byteIndex++] = (uint8_t)(WAVEFORM_FIFO_DEPTH);
    //搬移数据点位
    for(int idx = 0; idx < WAVEFORM_FIFO_DEPTH; idx++){
        waveData = oneFifoWaveData[idx];
        rsp[byteIndex++] = (uint8_t)(waveData >> 8);
        rsp[byteIndex++] = (uint8_t)(waveData);
    }
    //覆写帧长度
    rsp[4] = (uint8_t)((byteIndex - 6) >> 8);
    rsp[5] = (uint8_t)(byteIndex - 6);

    return byteIndex;
}

void sinDataInit(){
    int p = 0;
    for(int i=0; i < 9; i++){
        if(i%3 == 0)
            p = 0;
        else if(i%3 == 1)
            p = 0.66*3.14;
        else if(i%3 == 2)
            p = -0.66*3.14;
            
        for(int j=0; j<100; j++){
            sinRatio[i][j] = 1000*sin(0.02*3.14*j + p);
        }
    }
}

//将一组波形数据序列化为json数据, 返回一个json指针
struct json_object* realtimeGroupWaveDataToJson(uint32_t curGroupIndex){

    struct json_object* groupWaveDataObject, *fifoArrayObject;
    int oneGroupIndex = (curGroupIndex - 1) % WAVEFORM_GROUP_DEPTH;
    uint16_t* oneFifoWaveData = NULL;

    groupWaveDataObject = json_object_new_object();

    if(groupWaveDataObject == NULL){
        return NULL;
    }

    for(int fifoIndex = 0; fifoIndex < WAVEFORM_FIFO_QTY; fifoIndex++){
        fifoArrayObject = json_object_new_array_ext(WAVEFORM_FIFO_DEPTH);
        oneFifoWaveData = (uint16_t*)&(realtimeGroupDataBuff.groupWaveData[oneGroupIndex].waveData[fifoIndex]);
        for(int dataIndex = 0; dataIndex < WAVEFORM_FIFO_DEPTH; dataIndex++){
            json_object_array_add(fifoArrayObject, json_object_new_uint64(oneFifoWaveData[dataIndex]));
        }
        json_object_object_add(groupWaveDataObject, fifoName[fifoIndex], fifoArrayObject);
    }

    return groupWaveDataObject;
}

//将json数据反序列化为一组波形数据, 返回一个指针
struct oneGroupWaveData* realtimeGroupWaveDataFromJson(const char* strGroupWaveData){

    if(strGroupWaveData == NULL){
        return NULL;
    }

    struct oneGroupWaveData* oneGroupData = (struct oneGroupWaveData*)malloc(sizeof(struct oneGroupWaveData));
    if(oneGroupData == NULL){
        return NULL;
    }

    struct json_object* fifoArrayObject = NULL;
    struct json_object* arrayDataObject = NULL;
    struct json_object* groupWaveDataObject = json_tokener_parse(strGroupWaveData);
    
    for(int fifoIndex = 0; fifoIndex < WAVEFORM_FIFO_QTY; fifoIndex++){
        fifoArrayObject = json_object_object_get(groupWaveDataObject, fifoName[fifoIndex]);
        for(int dataIndex = 0; dataIndex < WAVEFORM_FIFO_DEPTH; dataIndex++){
            arrayDataObject = json_object_array_get_idx(fifoArrayObject, dataIndex);
            oneGroupData->waveData[fifoIndex][dataIndex] = (uint16_t)json_object_get_uint64(arrayDataObject);
        }
    }
    json_object_put(groupWaveDataObject);

    return oneGroupData;
}

//将json_object反序列化为一组波形数据, 返回一个指针
struct oneGroupWaveData* oneGroupWaveDataFromJsonObject(struct json_object* groupWaveDataObject){

    if(groupWaveDataObject == NULL){
        return NULL;
    }

    struct oneGroupWaveData* oneGroupData = (struct oneGroupWaveData*)malloc(sizeof(struct oneGroupWaveData));
    if(oneGroupData == NULL){
        return NULL;
    }

    struct json_object* fifoArrayObject = NULL;
    struct json_object* arrayDataObject = NULL;
    
    for(int fifoIndex = 0; fifoIndex < WAVEFORM_FIFO_QTY; fifoIndex++){
        fifoArrayObject = json_object_object_get(groupWaveDataObject, fifoName[fifoIndex]);
        for(int dataIndex = 0; dataIndex < WAVEFORM_FIFO_DEPTH; dataIndex++){
            arrayDataObject = json_object_array_get_idx(fifoArrayObject, dataIndex);
            oneGroupData->waveData[fifoIndex][dataIndex] = (uint16_t)json_object_get_uint64(arrayDataObject);
        }
    }

    return oneGroupData;
}

//将json对象反序列化为40组波形数据
int errorGroupWaveDataFromJsonObject(struct json_object* errorWaveDataObject){

    if(errorWaveDataObject == NULL){
        return -1;
    }

    char groupName[10];
    struct errorWaveData* errorWaveData = getErrorWaveDataBuff();
    struct json_object* oneGroupJsonObject = NULL;
    struct oneGroupWaveData* oneGroupData = NULL;

    for(int group = 1; group <= MAX_ERROR_WAVE_GROUP; group++){
        sprintf(groupName, "group%d", group);
        oneGroupJsonObject = json_object_object_get(errorWaveDataObject, groupName);
        oneGroupData = oneGroupWaveDataFromJsonObject(oneGroupJsonObject);
        memcpy(&(errorWaveData->errorWaveData[group - 1]), oneGroupData, sizeof(struct oneGroupWaveData));
        free(oneGroupData);
    }

    return 0;
}

//发生错误时，根据当前的时间戳录制40组错误波形到数据库
struct json_object* errorGroupWaveDataToJson(uint32_t curGroupIndex){

    uint8_t index = 1;
    uint32_t recordIndex = curGroupIndex - ERROR_WAVE_HEAD_GROUP_QTY;
    struct json_object* groupWaveDataObject = NULL;
    char groupName[10];

    struct json_object* errorWaveformObject = json_object_new_object(); //存储40组波形数据

    while(1){
        if(recordIndex <= realtimeGroupDataBuff.currentGroupIndex){
            groupWaveDataObject = realtimeGroupWaveDataToJson(recordIndex);
            sprintf(groupName, "group%d", index);
            json_object_object_add(errorWaveformObject, groupName, groupWaveDataObject);
//            printf("录制了一组数据%d, 当前组%d, index %d\n", recordIndex, realtimeGroupDataBuff.currentGroupIndex, index);
            recordIndex++;
            index++;
            if(index > 40) break;
        }
        usleep(100);
    }
    return errorWaveformObject;
}

#if 0

void WaveformSample_Thread(const void* pPara){

    Misc_InitThread(__func__);

    int fd = open(FPGA_PIN_DEV, O_RDWR);
    char val;
    uint16_t fifoChannData[WAVEFORM_FIFO_QTY] = {0};
    int sinIndex;
    time_t errTime;

    sinDataInit();

	if (fd < 0){
		printf("can't open /dev/fpga!\n");
        return -1;
	}

    while(1){
        read(fd, &val, 1); //阻塞等待FPGA给中断信号
//        memset(fifoChannData, 0, sizeof(fifoChannData));

        for(uint16_t index = 0; index < WAVEFORM_FIFO_DEPTH; index++){
//            sinIndex = (realtimeWaveData.rwdt_sampleDataIndex) % 100;
            for(uint16_t fifoIndex = 0; fifoIndex < WAVEFORM_FIFO_QTY; fifoIndex++){
                fifoChannData[fifoIndex] = waveformSampleFpgaFifoRead(fifoIndex);
//                fifoChannData[fifoIndex] = sinRatio[fifoIndex][sinIndex];
            }
//            printf("%d ", (int16_t)fifoChannData[0]);
            // 是否每个点都要采集
//            realtimeWaveData.rwdt_sampleDataIndex++;
            waveformSampleEnqueue(index, fifoChannData);
        }

        oneGroupWaveDataCopy(&(realtimeWaveData.rwdt_oneGroupWaveData));
        realtimeGroupDataBuff.currentGroupIndex++;

//        printf("realtime wave data group index %d\n",realtimeGroupDataBuff.currentGroupIndex);
#if 0
        if(realtimeGroupDataBuff.currentGroupIndex == 10){
            printf("发送错误消息\n");
            errorMsgSend(1);
        }
#endif    

//        usleep(50000);
    }
    
}
#else

//波形处理定时器
#define READ_CODE 0x4000
#define NONE_DATA_CODE 0x0000

static uint16_t last_state = NONE_DATA_CODE;
static uint16_t numCnt;

void realtimeWaveTimerThread(int signum){

    // struct timeval tv;
    uint16_t waveJudgeState;
    uint16_t fifoChannData[WAVEFORM_FIFO_QTY] = {0};

    // gettimeofday(&tv, NULL);
    // long began_read_time = tv.tv_sec*1000 + tv.tv_usec/1000;

    FpgaInf_Read(502, &waveJudgeState);
    // printf("当前code: %x\n", waveJudgeState);

    if((waveJudgeState == READ_CODE)){
        for(uint16_t index = 0; index < WAVEFORM_FIFO_DEPTH; index++){
            for(uint16_t fifoIndex = 0; fifoIndex < WAVEFORM_FIFO_QTY; fifoIndex++){
                fifoChannData[fifoIndex] = waveformSampleFpgaFifoRead(fifoIndex);
            }
            waveformSampleEnqueue(index, fifoChannData);
        }

        oneGroupWaveDataCopy(&(realtimeWaveData.rwdt_oneGroupWaveData));
        realtimeGroupDataBuff.currentGroupIndex++;
        numCnt = 0;
        printf("realtime wave data group index %d\n",realtimeGroupDataBuff.currentGroupIndex);
    }
    else{
        // printf("波形code无数据\n");
        numCnt++;
    }
    if(numCnt >= 4){
        printf("read slow\n");
    }
    last_state = waveJudgeState;

    // gettimeofday(&tv, NULL);
    // long end_read_time = tv.tv_sec*1000 + tv.tv_usec/1000;
    // printf("定时器运行耗时%d ms, 当前毫秒数%ld\n", end_read_time - began_read_time, end_read_time);

}

//初始化定时器
int waveTimerInit(timer_t* timerId, struct sigevent* sevp, struct itimerspec* it){

    if(!timerId || !sevp || !it) 
        return -1;

    memset(sevp, 0, sizeof(struct sigevent));
    sevp->sigev_signo = SIGUSR2;
    sevp->sigev_notify = SIGEV_SIGNAL;
    sevp->sigev_value.sival_ptr = timerId;

    if(timer_create(CLOCK_MONOTONIC, sevp, timerId) == -1){
        perror("timer_create failed!\n");
        return -1;
    }

    return 0;
}

//定时器，启动
int waveTimerStart(timer_t* timerId, struct itimerspec* it){

    if(!timerId || !it)
        return -1;

    it->it_interval.tv_sec = 0;    //25ms的时间间隔
    it->it_interval.tv_nsec = 25000000; 
    it->it_value.tv_sec = 0;    //暂定为75ms后启动定时器
    it->it_value.tv_nsec = 75000000;
    
    if(timer_settime(*timerId, TIMER_ABSTIME, it, NULL) == -1){
        perror("timer_settime failed!\n");
        return -1;
    }

    return 0;
}

void realtimeWaveGenerate(){

    uint16_t waveJudgeState;
    uint16_t fifoChannData[WAVEFORM_FIFO_QTY] = {0};

    FpgaInf_Read(502, &waveJudgeState);

    if((waveJudgeState == READ_CODE)){
        for(uint16_t index = 0; index < WAVEFORM_FIFO_DEPTH; index++){
            for(uint16_t fifoIndex = 0; fifoIndex < WAVEFORM_FIFO_QTY; fifoIndex++){
                fifoChannData[fifoIndex] = waveformSampleFpgaFifoRead(fifoIndex);
            }
            waveformSampleEnqueue(index, fifoChannData);
        }

        oneGroupWaveDataCopy(&(realtimeWaveData.rwdt_oneGroupWaveData));
        realtimeGroupDataBuff.currentGroupIndex++;
        numCnt = 0;
        printf("realtime wave data group index %d\n",realtimeGroupDataBuff.currentGroupIndex);
    }
    else{
        // printf("波形code无数据\n");
        numCnt++;
    }

    if(numCnt > 10){
        printf("read slow\n");
    }
}

static timer_t waveTimerId = NULL;

void WaveformSample_Thread(const void* pPara){

    Misc_InitThread(__func__);
    
    struct sigevent sevp;
    struct itimerspec it;
    int sockfd;
    uint32_t curGroupIndex;
    uint8_t rsp[1024];
    int rspLength, res;

    // signal(SIGUSR2, realtimeWaveTimerThread);

    // if(waveTimerInit(&waveTimerId, &sevp, &it) == -1){
    //     printf("waveTimerInit failed!\n");
    //     return;
    // }

    // 复位FPGA波形数据
    FpgaInf_Write(100, 288);

    // if(waveTimerStart(&waveTimerId, &it) == -1){
    //     printf("waveTimerStart failed!\n");
    //     return;
    // }

    // 开始数据采样, 降低采样率到3000
    FpgaInf_Write(100, 32);

    while(1){
        // Misc_RecordWaveIndex(realtimeGroupDataBuff.currentGroupIndex);
        // sleep(1);

        // 生成波形
        realtimeWaveGenerate();

        //获取发送实时波形的标志位;
        if(getRealtimeSyncSendFlag() == REALTIME_WAVE_SEND_START){
        //获取实时波形数据组的数据;
            if(getCurrentWaveDataGroupIndex() > getSendGroupIndex()){
                setSendGroupIndex(getCurrentWaveDataGroupIndex());
            }
            else if(getCurrentWaveDataGroupIndex() == getSendGroupIndex()){
                curGroupIndex = getCurrentWaveDataGroupIndex();
                sockfd = getRealtimeSyncSendSocketFd();
                for(int fifoIndex = 0; fifoIndex < WAVEFORM_FIFO_QTY; fifoIndex++){
                    rspLength = realtimeWaveDataPackageFrame(fifoIndex, curGroupIndex, rsp);
                    res = send(sockfd, rsp, rspLength, 0);
                    if(res < 0){
                        printf("MSH(%d) realtime wave data send ERROR\n",sockfd);
                        setRealtimeSyncSendFlag(REALTIME_WAVE_SEND_STOP);
                        setRealtimeSyncSendSocketFd(-1);
                        break;
                    }
                }
                // printf("realtime wave data send group index %d\n",getSendGroupIndex());
                sendGroupIndexIncrement();
            }   
        }
        
        if(realtimeGroupDataBuff.currentGroupIndex % 100 == 0)
            Misc_RecordWaveIndex(realtimeGroupDataBuff.currentGroupIndex);

        usleep(10000);
    }
    
}
#endif




